import * as THREE from "three";
import { changeMode } from "..";
import type { MenuItem } from "@imengyu/vue3-context-menu";
import { Part3DMesh, Loft3DMesh } from "../types/DrawingGroups/meshs";
import {
  AssemblyProductGroup,
  Product3DGroup,
  Sub3DGroup,
} from "../types/DrawingGroups/groups";
import { TraverseAndFilter } from "../helpers/GroupTraverseHelper";
import { AnimateDoorOpen, AnimateDoorClose } from "../animation/doorAnimate";

export class BaseMode {
  modeName: string;
  scene: THREE.Scene;
  dom: HTMLCanvasElement;
  camera: THREE.Camera;
  currentProductCube?: THREE.Mesh;
  mouseSenseCubes?: THREE.Mesh[];

  constructor(
    dom: HTMLCanvasElement,
    camera: THREE.Camera,
    scene: THREE.Scene
  ) {
    this.dom = dom;
    this.camera = camera;
    this.scene = scene;
    this.modeName = "base";
  }

  init() {}

  mousemove(e: MouseEvent) {}

  mousedown(e: MouseEvent) {}

  contextmenu(e: MouseEvent) {}

  onExitMode() {}

  onStepInMode() {}

  raycasting: boolean = false;
  funcRaycaster(e: MouseEvent) {
    if (this.mouseSenseCubes === undefined) {
      return;
    }
    if (this.raycasting) {
      return;
    }
    this.raycasting = true;
    //raycaster 参考https://www.cnblogs.com/smedas/p/12445201.html
    //event.clientX/Y是整个以window左上为基础的坐标，不是canvas所在dom的
    var raycaster = new THREE.Raycaster(); // create once
    var mouse = new THREE.Vector2(); // create once
    //将鼠标点击位置的屏幕坐标转成threejs中的标准坐标
    //转换后的坐标系：原点（0，0）位于dom的正中心，xy都是从-1到1
    //https://discourse.threejs.org/t/custom-canvas-size-with-orbitcontrols-and-raycaster/18742
    const rect = this.dom.getBoundingClientRect();
    mouse.x = ((e.clientX - rect.left) / (rect.right - rect.left)) * 2 - 1;
    mouse.y = -((e.clientY - rect.top) / (rect.bottom - rect.top)) * 2 + 1;
    raycaster.setFromCamera(mouse, this.camera);

    const intersects = raycaster.intersectObjects(this.findMouseSenseCubes());
    //console.log("射线器返回的对象", intersects);
    // intersects.length大于0说明，说明选中了模型
    if (intersects.length > 0 && intersects[0].object instanceof THREE.Mesh) {
      // 选中模型的第一个模型，设置为红色
      //intersects[0].object.material.color.set(0xff0000);
      intersects[0].object.visible = true;
      if (this.currentProductCube === undefined) {
        this.currentProductCube = intersects[0].object;
      } else if (this.currentProductCube != intersects[0].object) {
        this.currentProductCube.visible = false;
        this.currentProductCube = intersects[0].object;
      }
    } else {
      //没有选中，要把cube重置为undefined
      if (this.currentProductCube) {
        this.currentProductCube.visible = false;
      }
    }
    this.raycasting = false;
  }

  getCurrentModelInfoMenuItems(): MenuItem[] {
    if (
      this.currentProductCube &&
      (this.currentProductCube.parent instanceof Product3DGroup ||
        this.currentProductCube.parent instanceof Sub3DGroup)
    ) {
      var [model] = this.currentProductCube.parent.model.kujialeModel!;
      return [
        {
          label: `尺寸: ${model.boxSize!.x}/${model.boxSize!.z}/${
            model.boxSize!.y
          }`,
        },
        {
          label: `坐标: ${model.position.x}/${model.position.y}/${model.position.z}`,
        },
        {
          label: `旋转: ${model.rotateDegree.x}/${model.rotateDegree.y}/${model.rotateDegree.z}`,
        },
      ];
    }
    return [];
  }
  getCurrentMenuTextureList(): MenuItem[] {
    var list: string[] = [];
    this.currentProductCube?.parent?.children.forEach((s) => {
      if (s instanceof Product3DGroup || s instanceof Sub3DGroup) {
        this.getSubTextureList(s, list);
      }
    });
    return list.map<MenuItem>((l) => {
      return { label: l };
    });
  }

  getSubTextureList(group: Product3DGroup | Sub3DGroup, list: string[]) {
    group.children.forEach((s) => {
      if (s instanceof Product3DGroup || s instanceof Sub3DGroup) {
        this.getSubTextureList(s, list);
      } else if (s instanceof Part3DMesh || s instanceof Loft3DMesh) {
        var [json] = s.model.kujialeModel!;
        if (list.find((it) => it == json.textureName) == undefined) {
          list.push(json.textureName);
        }
      }
    });
  }

  findMouseSenseCubes(): THREE.Mesh[] {
    return [];
  }

  findDoorsAndAction(open: boolean, callback: () => void) {
    let doors = TraverseAndFilter(
      this.currentProductCube?.parent?.children!,
      (cm) => {
        return cm.prodCatId == 498 || cm.prodCatId == 1043;
      },
      (cm) => false,
      (cg) => (cg.model.doorClosed = !open),
      (cg, cm) => {
        //nothing
       
          cg.model.doorClosed = !open;
      }
    );
    doors.forEach((d) => (open ? AnimateDoorOpen(d) : AnimateDoorClose(d)));
    callback();
  }
}
